Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.

...powered by www.netzwerkartist.de...

 <<   zurück
Visual Basic 2005 von Andreas Kühnel
Das umfassende Handbuch
Buch: Visual Basic 2005

Visual Basic 2005
1.233 S., mit 2 CDs, 59,90 Euro
Galileo Computing
ISBN 3-89842-585-1
gp Kapitel 5 Das Klassendesign (Teil 2)
  gp 5.1 Statische Klassenkomponenten
    gp 5.1.1 Die Realisierung eines Objektzählers
    gp 5.1.2 Zugriff auf statische Komponenten
    gp 5.1.3 Statische Klassenvariable in der Klasse »Circle«
    gp 5.1.4 Klassenspezifische Methoden
    gp 5.1.5 Statische Methoden in der Klasse »Circle«
    gp 5.1.6 Statische Klasseninitialisierer
    gp 5.1.7 Zusammenfassung
  gp 5.2 Delegaten
    gp 5.2.1 Einführung in das Prinzip der Delegaten
    gp 5.2.2 Zusammenfassung der Arbeitsschritte
    gp 5.2.3 Vereinfachter Aufruf eines Delegaten
  gp 5.3 Ereignisse eines Objekts
    gp 5.3.1 Ergänzung eines Ereignisses in einer Ereignisquelle
    gp 5.3.2 Die Behandlung eines Ereignisses im Ereignisempfänger
    gp 5.3.3 Ereignisse mit Übergabeparameter
    gp 5.3.4 Die Handles-Klausel
    gp 5.3.5 Die Registrierung eines Ereignishandlers mit »AddHandler«
    gp 5.3.6 Zusammenfassung
  gp 5.4 Strukturen – eine Sonderform der Klassen
    gp 5.4.1 Die Definition einer Struktur
    gp 5.4.2 Initialisieren einer Struktur
    gp 5.4.3 Ereignisse in einer Struktur
    gp 5.4.4 Änderung der Klasse »Circle«
    gp 5.4.5 Zusammenfassung der Unterscheidungsmerkmale Klasse – Struktur
  gp 5.5 Enumerationen (Aufzählungen)
    gp 5.5.1 Alle Mitglieder einer Aufzählung durchlaufen
  gp 5.6 Referenz- und Wertetypen
    gp 5.6.1 Typumwandlung mit Boxing
    gp 5.6.2 Die Unboxing-Konvertierung
    gp 5.6.3 Zusammenfassung
  gp 5.7 Namensräume (Namespaces)
    gp 5.7.1 Zugriff auf Namespaces
    gp 5.7.2 Die »Imports«-Anweisung
    gp 5.7.3 Aliasnamen zur Vermeidung von Mehrdeutigkeiten
    gp 5.7.4 Aufrufe mit »Global« umleiten
    gp 5.7.5 Namespaces festlegen
    gp 5.7.6 Zusammenfassung


Galileo Computing

5.4 Strukturen – eine Sonderform der Klassen  downtop

Bisher haben wir Objekte erzeugt, indem wir eine Klasse instanziierten. Objekte beanspruchen Systemressourcen, denn mit jedem Objekt ist ein Verwaltungsoverhead verbunden. Bei einzelnen Objekten fällt das kaum ins Gewicht; ein Objekt-Array, das möglicherweise Tausende typgleicher Objekte enthält, kann die Systemleistung jedoch spürbar negativ beeinflussen.

In .NET gibt es aus diesem Grund ein Konstrukt, das sich ähnlich wie eine Klasse verhält, dabei jedoch ressourcenschonend agiert, andererseits aber auch bestimmten Einschränkungen unterliegt: die Struktur. Eine Struktur wird von der Laufzeitumgebung als Wertetyp behandelt.


Galileo Computing

5.4.1 Die Definition einer Struktur  downtop

Eine Struktur beschreibt einen Datentyp, der sich aus Elementen verschiedener Typen zusammensetzt, die miteinander in einer festen Beziehung stehen und somit eine in sich geschlossene Einheit bilden. Stellen Sie sich vor, Sie wollten ein Automobil beschreiben, das durch einen Preis, Höchstgeschwindigkeit und Hubraum gekennzeichnet ist. Außerdem soll das Auto die Methoden Fahren und Hupen veröffentlichen. Die Klassendefinition könnte folgendermaßen lauten:


Public Class Car
Public Preis As Decimal
Public Höchstgeschwindigkeit As Single
Public Hubraum As Single
Public Sub Fahren()
' Anweisungen
End Sub
Public Sub Hupen()
' Anweisungen
End Sub
End Class

Tatsächlich unterscheidet sich die analoge Definition einer Struktur Car kaum von der einer Klasse – abgesehen vom Austausch des Schlüsselwortes class durch Structure:


Public Structure Car {
...
End Structure

Im ersten Moment mag das zu der Schlussfolgerung verleiten, eine Klasse grundsätzlich durch eine Struktur ersetzen zu können. Wie im weiteren Verlauf dieses Kapitels aber noch gezeigt wird, haben Strukturen im Vergleich zu den Klassen geringere Fähigkeiten.

Die Bestätigung der Aussage, eine Struktur sei ein Wertetyp, wird schon bei der Deklaration einer Strukturvariablen deutlich. Würde der Typ Car als Klasse definiert, müsste vor dem ersten Aufruf eine Instanz durch das Aufrufen des Operators New erzeugt werden:


' Car liegt als Class-Definition vor
Dim myCar As Car = New Car()
myCar.Hubraum = 1900

Eine Struktur wird demgegenüber von der Laufzeitumgebung jedoch wie die Variable eines elementaren Datentyps eingesetzt, da kein Verweis damit verknüpft ist:


' Car liegt als Structure-Definition vor
Dim myCar As Car

Der Zugriff auf die Elemente einer Struktur erfolgt ebenfalls mit dem Punktoperator, z.  B.:


myCar.Hubraum = 1900

Um eine Struktur zu definieren, bieten sich folgende Möglichkeiten an:

gp  eigenständig in einer separaten Quellcodedatei
gp  parallel neben anderen Klassen und Strukturen in einer Quellcodedatei
gp  im Deklarationsabschnitt einer Klasse

Die lokale Definition innerhalb einer Methode ist hingegen nicht erlaubt und führt zu einer Fehlermeldung.

Eigenständige Strukturdefinition

Strukturen können entweder Public oder Friend sein. Wird kein Zugriffsmodifizierer angegeben, gilt eine Struktur Public.

Bei der Festlegung eines Feldes vom Typ einer Struktur in einer Klasse ist dem Zugriffsmodifizierer besondere Beachtung zu schenken. Betrachten Sie dazu das folgende Codefragment in einer Anwendung vom Typ Klassenbibliothek:


Friend Structure Person
Public Name as String
Public Alter As Integer
End Structure
Public Class MyOwnClass
Public Pers As Person
End Class

Die Struktur Person ist als Friend definiert und beschränkt die Sichtbarkeit auf die aktuelle Assembly, in diesem Fall also auf die Klassenbibliothek. Die Klasse MyOwnClass ihrerseits ist Public definiert.

Der Code birgt in sich einen Widerspruch. In der öffentlichen Klasse ist das öffentliche Feld Pers vom Typ Person enthalten. Die Sichtbarkeit des Typs Person ist per Definition jedoch auf die aktuelle Anwendung, also auf die Klassenbibliothek, begrenzt. Tatsächlich wird die Entwicklungsumgebung diesen Widerspruch auch sofort mit einer Fehlermeldung quittieren, da gegen die folgende Regel verstoßen wird:


Ist ein Feld vom Typ einer Struktur, kann das Feld nicht öffentlicher sein als die Definition der Struktur.



Galileo Computing

5.4.2 Initialisieren einer Struktur  downtop

Eine Struktur ist die Beschreibung eines Datentyps. Um das Objekt einer Struktur nutzen zu können, benötigt man eine Variable dieses Typs. Im folgenden Beispiel ist die Struktur Person mit den Feldern Name und Alter definiert. In der Main-Methode wird die Variable pers vom Typ Person deklariert, und den Feldern werden Werte zugewiesen.


Module Module1
Sub Main()
Dim pers As New Person
pers.Name = "Willi Jakob"
pers.Alter = 35
End Sub
End Module
Structure Person
Public Name As String
Public Alter As Integer
End Structure

Der Name (»Willi Jakob«) und das Alter (35) sind einem ganz bestimmten Element zugeordnet, nämlich pers. Das erinnert an die Instanzvariablen einer Klasse, die ebenfalls objektgebunden sind. Der Vergleich ist auch nicht falsch, denn eine Strukturvariable ist einem Objektverweis sehr ähnlich, was durch die zweite Variante, eine Variable vom Typ einer Struktur zu deklarieren, besonders deutlich wird:


pers.Name = "Willi Jakob"
pers.Alter = 35

Die Syntax ist dieselbe wie bei der Instanziierung einer Klasse und deutet bereits darauf hin, dass es innerhalb einer Struktur einen Konstruktor geben muss, der parameterlos ist. Mit New wird dieser Konstruktor aufgerufen, der, wie auch der Konstruktor einer Klasse, die Felder des Objekts initialisiert.

Deklarieren Sie ein Objekt vom Typ einer Struktur mit New, sind alle Felder initialisiert und ermöglichen einen sofortigen Zugriff. Verzichten Sie auf den New-Operator, muss einem Feld zuerst ein Wert zugewiesen werden, bevor es ausgewertet werden kann.

Aus diesem Grund lehnt der VB-Compiler die Kompilierung des folgenden Codefragments ab: In der vierten Anweisung wird versucht, den Inhalt des noch uninitialisierten Feldes an der Konsole anzuzeigen.


Dim pers1 As Person = New Person()
Dim pers2 As Person
Console.WriteLine(pers1.Name)
Console.WriteLine(pers2.Name)


Galileo Computing

5.4.3 Ereignisse in einer Struktur  downtop

Eine Struktur ist mit Fähigkeiten ausgestattet, die denen einer Klasse ähnlich sind: Sie kann Konstruktoren, Methoden, Eigenschaften und Ereignisse enthalten. Der Zugriff auf die Strukturmitglieder erfolgt in derselben Weise wie bei einer Klasse – nur die Fähigkeit eines auf einer Struktur basierenden Objekts, Ereignisse auslösen zu können, unterliegt anderen Richtlinien, denn die Objektvariable darf nicht mit WithEvents deklariert werden. Stattdessen werden die Ereignishandler mit AddHandler beim betreffenden Objekt registriert.

Im folgenden Codefragment wird in der Struktur EventTest das Ereignis SayHallo definiert, das beim Aufruf der Methode DoEvent ausgelöst wird:


Public Structure EventTest
Public Event SayHallo()
Public Sub DoEvent()
RaiseEvent SayHallo()
End Sub
End Structure

Wäre EventTest eine Klasse, könnten wir mit


Dim WithEvents obj As EventTest

auf die ausgelösten Ereignisse reagieren. Weil EventTest aber als Struktur vorliegt, erzeugt diese Art der Deklaration einen Fehler und nötigt uns, den Weg über AddHandler zu beschreiten, beispielsweise:


Sub Main()
Dim obj As EventTest
AddHandler obj.SayHallo, AddressOf MyEventProc
obj.DoEvent()
Console.ReadLine()
End Sub
Public Sub MyEventProc()
Console.WriteLine("Ich wurde von einem EventTest-Objekt ausgelöst")
End Sub


Galileo Computing

5.4.4 Änderung der Klasse »Circle«  downtop

Wir wollen uns nun erneut der Klasse Circle zuwenden. Grundsätzlich wäre es denkbar, die Klasse Circle in eine Strukturdefinition umzuschreiben. Da wir Circle jedoch später in eine Vererbungshierarchie zwingen, kommt diese Änderung nicht in Betracht, da Strukturen grundsätzlich nicht abgeleitet werden können. An einer anderen Stelle bietet es sich allerdings an, die aktuelle Implementierung durch eine Struktur zu ersetzen: Es handelt sich dabei um die beiden Mittelpunktkoordinaten intXKoordinate und intYKoordinate, die nun durch die Struktur Point beschrieben werden sollen.


Hinweis

In der .NET-Klassenbibliothek ist mit System.Drawing.Point eine sehr ähnliche Struktur bereits vordefiniert und würde sich gleichermaßen anbieten.


Point ist sehr einfach aufgebaut und hat nur die beiden Felder xKoordinate und yKoordinate, die später den Mittelpunkt eines Kreisobjekts beschreiben sollen. Außerdem enthält die Struktur einen zweiparametrigen Konstruktor, dem beim Aufruf die Punktkoordinaten übergeben werden.


Public Structure Point
Public X As Integer
Public Y As Integer
Public Sub New(ByVal xKoordinate As Integer, _
ByVal yKoordinate As Integer)
X = xKoordinate
Y = yKoordinate
End Sub
End Structure

In der Klasse Circle zieht unsere Absicht selbstverständlich Änderungen nach sich. Zunächst werden die beiden Felder intXKoordinate und intYKoordinate durch ein Feld vom Typ der Struktur Point ersetzt, also:


Private center As Point

Von der Einführung der Struktur Point ist auch der Konstruktor betroffen, der die beiden Mittelspunktkoordinaten in seinen Parametern erwartet.


Public Sub New(ByVal radius As Double, ByVal x As Integer, _
ByVal y As Integer)
Me.New(radius)
center.X = x
center.Y = y
End Sub

Die beiden Eigenschaften XKoordinate und YKoordinate sollen auch weiterhin die Möglichkeit bieten, ein Kreisobjekt horizontal oder vertikal zu verschieben bzw. die einzelnen Positionswerte zu ermitteln. Die Implementierung muss auch hier an das neue Feld center angepasst werden.


Public Property XKoordinate() As Integer
Get
Return center.X
End Get
Set(ByVal Value As Integer)
center.X = Value
End Set
End Property
Public Property YKoordinate() As Integer
Get
Return center.Y
End Get
Set(ByVal Value As Integer)
center.Y = Value
End Set
End Property

Eine gute Klassendefinition zeichnet sich nicht nur dadurch aus, die Implementierung auf das Notwendigste zu beschränken, sondern deckt auch die Fälle ab, die für einen Benutzer unter Umständen sinnvoll sein könnten. Sehen wir uns dazu an dieser Stelle noch einmal die beiden Eigenschaften XKoordinate und YKoordinate an. Soll der Mittelpunkt eines Kreisobjekts diagonal verschoben werden, sind zwei Anweisungen notwendig. Vorteilhafter ist es, dasselbe mit einer Anweisung zu erreichen. Die Verbesserung soll durch eine Methode erzielt werden, die wir als MoveXY bezeichnen und die ein Point-Objekt vom Aufrufer entgegennimmt:


Public Sub MoveXY(ByVal newCenterPoint As Point)
center = newCenterPoint
End Sub

Da eine Struktur ein Wertetyp ist, schreiben sich die Felder X und Y der im Parameter newCenterPoint übergebenen Koordinaten in die gleich lautenden Felder von center.

Sehen wir uns nun in einem Codefragment an, wie einfach es ist, diese Methode zu benutzen. Es wird dabei davon ausgegangen, dass ein konkretes Circle-Objekt namens kreis vorliegt. Mit


Dim newPoint As Point = New Point(150, 315)
kreis.MoveXY(newPoint)

übergeben wir der Methode ein Point-Objekt. Benötigen wir dieses Objekt zur Laufzeit der Anwendung nicht mehr, kann es auch in der Argumentliste erzeugt werden.


kreis.MoveXY(New Point(150, 315))

Zuletzt ergänzen wir die Klasse Circle noch um einen Konstruktor, der neben dem Radius eine Point-Referenz als Argument erwartet:


Public Sub New(ByVal radius As Double, ByVal pt As Point)
Me.New(radius)
center = pt
End Sub

Damit wird eine Instanziierung der Klasse mit


Dim kreis As Circle = New Circle(2, New Point(5, 12))

möglich.

Den Code des Beispiels CircleApplication mit allen Änderungen, die wir bisher in diesem Kapitel vorgenommen haben, finden Sie auf der Buch-CD unter:

...\Kapitel 5\CircleApplication_3


Galileo Computing

5.4.5 Zusammenfassung der Unterscheidungsmerkmale Klasse – Struktur  toptop

Klassen und Strukturen stellen in vielerlei Hinsicht dieselben Möglichkeiten zur Verfügung. Beispielsweise können in Strukturen Methoden und Ereignisse definiert sowie Ereignishandler implementiert werden. Die Methoden können nach denselben Regeln wie in den Klassen überladen werden.

Wie aber eingangs dieses Abschnitts bereits angedeutet wurde, gibt es einige Einschränkungen, die in Kauf genommen werden müssen, wenn Sie sich für eine Struktur anstelle einer Klasse entscheiden:

gp  Strukturen können weder die Eigenschaften und Methoden anderer Klassen oder Strukturen erben, noch können sie ihre eigenen Features anderen Klassen oder Strukturen vererben. Von dieser Regel gibt es nur eine Ausnahme: Implizit beerben Strukturen die Klasse ValueType, die ihrerseits direkt aus der Klasse Object abgeleitet ist und deren Methoden in passender Weise überschreibt.
gp  Standardmäßig stellt eine Struktur einen parameterlosen Konstruktor bereit, der mit
Dim x As MyStruct
aufgerufen wird. Alternativ ist eine Strukturvariable aber auch mit
Dim x As New MyStruct()
deklarierbar, was wiederum die Ähnlichkeit zu den Klassen verdeutlicht. In einer Struktur dürfen weitere Konstruktoren definiert werden. Diese müssen jedoch parametrisiert sein, denn das Überschreiben des parameterlosen Konstruktors ist nicht zulässig.
gp  Wird ein parametrisierter Konstruktor einer Struktur aufgerufen, muss die Variable mit dem New-Operator initialisiert werden. Aber Vorsicht ist hierbei geboten, denn das folgende Codefragment führt zu einer zweifachen Initialisierung der Variablen myStruct:
Dim myOwnStruct As MyStruct 
myOwnStruct = New MyStruct(2)
In der ersten Zeile wird der parameterlose Konstruktor der Struktur aufgerufen, in der zweiten ein parametrisierter. Wäre der zugrunde liegende Typ MyStruct eine Klasse, würde es nur zu einem Konstruktoraufruf kommen.
gp  Der Gültigkeitsbereich von Eigenschaften und Methoden wird durch die Modifizierer Public, Friend und Private beschrieben, bei Datenmembern gilt zusätzlich noch Dim. Mit Dim deklarierte Datenmember einer Struktur gelten immer als öffentlich, sind also Public. Zur Erinnerung: In einer Klassendefinition wäre eine so deklarierte Instanzvariable Private.
gp  Sollte es erforderlich sein, können Sie Stukturen auch ineinander verschachteln. Die einzelnen Ebenen werden – wie üblich – durch Punktnotation voneinander getrennt.
 <<   zurück
  
  Zum Katalog
Zum Katalog: Visual Basic 2005
Visual Basic 2005
bestellen
 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps
Zum Katalog: Visual C# 2005






 Visual C# 2005


Zum Katalog: Fortgeschrittene Programmierung mit Visual C# 2005






 Fortgeschrittene
 Programmierung
 mit Visual C# 2005


Zum Katalog: Das Programmierhandbuch SQL Server 2005






 Das Programmier-
 handbuch
 SQL Server 2005


Zum Katalog: Einstieg in Visual Basic 2005






 Einstieg in
 Visual Basic 2005


Zum Katalog: Einstieg in Visual C# 2005






 Einstieg in
 Visual C# 2005


Zum Katalog: Konzepte und Lösungen für Microsoft-Netzwerke






 Konzepte und
 Lösungen für
 Microsoft-Netzwerke


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo








Copyright © Galileo Press 2007
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Galileo Computing]

Galileo Press, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de